#define _CRT_SECURE_NO_WARNINGS 1
#pragma once
#include<iostream>
#include<string>
using namespace std;

class A 
{
public:
	A()
	{}
	A(const A& a)
	{
		cout << "A(const A& a)" << endl;
	}
private:
	int _a;
	string a;
};
class B : public A
{
public:
	B()
	{}
	B(const B& a)
	{
		cout << "B(const B& a)" << endl;
	}
private:
	int b;
	string _b;;
};
int main()
{
	B b;
	A a = b;
	return 0;
}

//基类1
class Base1
{
public:
	virtual void func1() { cout << "Base1::func1()" << endl; }
	virtual void func2() { cout << "Base1::func2()" << endl; }
private:
	int _b1;
};
//基类2
class Base2
{
public:
	virtual void func1() { cout << "Base2::func1()" << endl; }
	virtual void func2() { cout << "Base2::func2()" << endl; }
private:
	int _b2;
};
//派生类多继承
class Derive : public Base1, public Base2
{
public:
	virtual void func1() { cout << "Derive::func1()" << endl; }
	virtual void func3() { cout << "Derive::func3()" << endl; }
private:
	int _d1;
};

typedef void(*VFPTR)();//VFPTR是函数指针类型,虚函数指针 ,我们这里写的虚函数都是无参,返回值为void类型的
//VFPTR* :指向函数指针的指针,  虚表指针指向的是虚表,虚表相当于函数指针数组, 数组名是数组首元素地址,所以虚表指针的类型为: VFPTR*

//打印虚表内容
//void PirntVFT(VFPTR table[]) table是一个数组,数组元素类型是函数指针
void PrintVFT(VFPTR* ptr)
{
	//printf("虚表的地址为:%p\n",ptr);

	//ptr相当于是虚表指针vfptr,*ptr可以得到其内容为虚表的地址
	//虚函数表本质是一个存虚函数指针的指针数组,VS下这个数组最后面放了一个nullptr
	for (int i = 0; ptr[i] != nullptr; i++)
	{
		printf("ptr[%d]:%p --->", i, ptr[i]);
		//调用虚函数测试一下
		VFPTR fun = ptr[i];
		fun();//也可以写成: ptr[i]()
	}
	cout << endl;
}

int main()
{
	Base1 b1;
	cout << "Base1对象的虚表:" << endl;
	PrintVFT((VFPTR*)(*(void**)&b1));

	Base2 b2;
	cout << "Base2对象的虚表:" << endl;
	PrintVFT((VFPTR*)(*(void**)&b2));

	Derive d;
	cout << "子类对象的第一个虚表:" << endl;
	PrintVFT((VFPTR*)(*(void**)&d));

	cout << "子类对象的第二个虚表:" << endl;
	PrintVFT((VFPTR*)(*(void**)((char*)&d + sizeof(Base1))));
	return 0;
}

class A
{
public:
	 virtual void func();
};
void A::func()
{
		cout << "A::void func()" << endl;
}
class B : public A
{
public:
	 virtual void func();
};
void B::func()
{
	cout << "B::void func()" << endl;
}
int main()
{
	A aa;
	aa.func();
	return 0;
}